/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.model.tree;

import java.util.ArrayList;
import java.util.List;

import org.zhiqim.kernel.annotation.AnNonnull;

/**
 * 树对象模型
 *
 * @version v1.0.0 @author zouzhigang 2017-8-12 新建与整理
 */
public class Tree<E>
{
    private final Treer<E> treer;           //判断器
    
    private final E self;                   //自身节点对象
    private final Tree<E> parent;           //父节点
    private final List<Tree<E>> children;   //子节点列表
    
    private final boolean isLastNode;       //自身节点是否是兄弟中最后一个节点
    
    /**
     * 生成树对象，要求提供根节点和判断器
     * 
     * @param root      根对象
     * @param treer     判断器
     */
    public Tree(E root, Treer<E> treer)
    {
        this.self = root;
        this.treer = treer;
        this.parent = null;
        this.children = new ArrayList<>();
        this.isLastNode = true;
    }
    
    /** 内部使用 */
    private Tree(E self, Tree<E> parent, boolean isLastNode)
    {
        this.self = self;
        this.parent = parent;
        this.treer = parent.treer;
        this.children = new ArrayList<>();
        this.isLastNode = isLastNode;
    }
    
    /***********************************************************************/
    //生成模型
    /***********************************************************************/
    
    public Tree<E> build(List<E> list)
    {
        List<E> cList = new ArrayList<>();
        for (E item : list)
        {
            if (treer.isChildNode(self, item))
                cList.add(item);
        }
        
        int size = cList.size();
        for (int i=0;i<size;i++)
        {
            Tree<E> child = new Tree<E>(cList.get(i), this, i == size -1);
            child.build(list);
            children.add(child);
        }
        
        return this;
    }
    
    /***********************************************************************/
    //模型获取&设置方法
    /***********************************************************************/
    
    @AnNonnull
    public E self()
    {
        return self;
    }
    
    @AnNonnull
    public List<Tree<E>> children()
    {
        return children;
    }

    public boolean hasChildren()
    {
        return !children.isEmpty();
    }
    
    public boolean hasNextNode()
    {
        return !isLastNode;
    }

    public boolean isLastNode()
    {
        return isLastNode;
    }
    
    /**
     * 父级是否最后节点，用于判断是使用blank还是vertline
     * 
     * @param level 向上父级层次，自己时level=0,父节点时leve=1，父父节点时level=2
     * @return      是否是兄弟节点中的最后一个节点
     */
    public boolean isLastNode(int level)
    {
        Tree<E> tree = this;
        for (int i=0;i<level;i++)
        {
            tree = tree.parent;
        }
        return tree.isLastNode;
    }
    
    /** 数目 */
    public int size()
    {
        int size = 1;
        for (Tree<E> tree : children)
        {
            size += tree.size();
        }
        return size;
    }
}
